package io.gitee.shengzheng1999.esbcommon.common.utils;

import java.lang.reflect.Method;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import io.gitee.shengzheng1999.esbcommon.exception.BaseException;
import io.gitee.shengzheng1999.esbcommon.exception.ExceptionCodes;
import com.alibaba.fastjson.JSONObject;

/**
 * @className		: Utility
 * @description	: 工具类
 * @summary		:
 * @history		:
 * ------------------------------------------------------------------------------
 * date			version		modifier		remarks                   
 * ------------------------------------------------------------------------------
 * 2021/01/01	1.0.0		sheng.zheng		初版
 *
 */
public class Utility {
	private static final String charset = "utf-8";
    

	
	//========================= String操作 ======================================    
	/**
	 * 
	 * @methodName		: trimLeftAndRight
	 * @description	: 去掉给定字符串的首尾指定字符 
	 * @param src		: 输入字符串
	 * @param trimStr	: 需要去掉的指定字符
	 * @return			: 去掉首尾指定字符后的字符串
	 * @history		:
	 * ------------------------------------------------------------------------------
	 * date			version		modifier		remarks                   
	 * ------------------------------------------------------------------------------
	 * 2021/01/01	1.0.0		sheng.zheng		初版
	 *
	 */
	public static  String trimLeftAndRight(String src,String trimStr) {
		String regex = "^" + trimStr + "*|" + trimStr + "*$";
		return src.replaceAll(regex, "");
	}	
	
	/**
	 * 
	 * @methodName		: trimRight
	 * @description	: 去掉给定字符串的尾部指定字符
	 * @param sValue	: 输入字符串
	 * @param sTrim		: 需要去掉的指定字符
	 * @return			: 处理后的字符串
	 * @history		:
	 * ------------------------------------------------------------------------------
	 * date			version		modifier		remarks                   
	 * ------------------------------------------------------------------------------
	 * 2023/05/02	1.0.0		sheng.zheng		初版
	 *
	 */
	public static String trimRight(String src,String trimStr) {
		String strTrim = Pattern.quote(trimStr);
		String regex = strTrim + "*$";
		return src.replaceAll(regex, "");
	}		
	
	/**
	 * 
	 * @methodName		: getURLEncoderStr
	 * @description	: 获取URLEncoder字符串
	 * @param str		: 输入字符串
	 * @return			: URLEncoder后的字符串
	 * @history		:
	 * ------------------------------------------------------------------------------
	 * date			version		modifier		remarks                   
	 * ------------------------------------------------------------------------------
	 * 2021/01/01	1.0.0		sheng.zheng		初版
	 *
	 */
	public static String getURLEncoderStr(String str) {
		String sRet = "";
		try {
			sRet = URLEncoder.encode(str, charset);
		}catch(Exception e) {
			LogUtil.error(e);
		}
		
		return sRet;
	}
	
	public static String getUrlDecodeStr(String str) {
		String sRet = "";
		try {
			sRet = URLDecoder.decode(str, charset);
		}catch(Exception e) {
			LogUtil.error(e);
		}
		
		return sRet;		
	}	
	
	/**
	 * 
	 * @methodName		: parseThirdResponse
	 * @description	: 解析第三方响应字符串
	 * @param content	: 响应字符串
	 * @return			: JSON对象
	 * @history		:
	 * ------------------------------------------------------------------------------
	 * date			version		modifier		remarks                   
	 * ------------------------------------------------------------------------------
	 * 2021/01/01	1.0.0		sheng.zheng		初版
	 *
	 */
	public static JSONObject parseThirdResponse(String content) {
		JSONObject joResult = JSONObject.parseObject(content);
		return joResult;
	}
	
	/**
	 * 
	 * @methodName		: underlineToCamel
	 * @description	: 下划线转驼峰
	 * @param strInput	: 输入字符串
	 * @return			: 驼峰表示
	 * @history		:
	 * ------------------------------------------------------------------------------
	 * date			version		modifier		remarks                   
	 * ------------------------------------------------------------------------------
	 * 2022/01/23	1.0.0		sheng.zheng		初版
	 *
	 */
	public static String underlineToCamel(String strInput) {
		String camel = "";
		String str = strInput.toLowerCase();
		String[] splits = str.split("\\_");
		for (int i = 0; i <splits.length; i++) {
			String item = splits[i];
			if (i > 0) {
				item = item.substring(0,1).toUpperCase() + item.substring(1,item.length());
			}
			camel += item;
		}
		return camel;
	}
	
	/**
	 * 
	 * @methodName		: underlineToCamel
	 * @description	: 字典key，下划线转驼峰
	 * @param map		: 输入字典
	 * @return			: key为驼峰的字典
	 * @history		:
	 * ------------------------------------------------------------------------------
	 * date			version		modifier		remarks                   
	 * ------------------------------------------------------------------------------
	 * 2022/01/23	1.0.0		sheng.zheng		初版
	 *
	 */
	public static Map<String, Object> underlineToCamel(Map<String, Object> map) {
		Map<String, Object> retMap = new HashMap<String, Object>();
		String camel = "";
		Object oVal = null;
		for(String key : map.keySet()) {
			camel = underlineToCamel(key);
			oVal = map.get(key);
			retMap.put(camel, oVal);
		}
		return retMap;
	}
	
	/**
	 * 
	 * @methodName		: underlineToCamel
	 * @description	: 字典列表，字典key下划线转驼峰
	 * @param itemList	: 字典列表
	 * @return			: 字典key下划线转驼峰
	 * @history		:
	 * ------------------------------------------------------------------------------
	 * date			version		modifier		remarks                   
	 * ------------------------------------------------------------------------------
	 * 2022/01/23	1.0.0		sheng.zheng		初版
	 *
	 */
	public static List<Map<String, Object>> underlineToCamel(List<Map<String, Object>> itemList) {
		List<Map<String, Object>> retList = new ArrayList<Map<String, Object>>();
		Map<String, Object> map = null;
		for(Map<String, Object> item : itemList) {
			map = underlineToCamel(item);
			retList.add(map);
		}
		return retList;
	}	
	
	/**
	 * 
	 * @methodName		: makeFirstUpper
	 * @description	: 将首字母转为大写
	 * @param sInput	: 输入字符串
	 * @return			: 转换后的字符串
	 * @history		:
	 * ------------------------------------------------------------------------------
	 * date			version		modifier		remarks                   
	 * ------------------------------------------------------------------------------
	 * 2023/04/11	1.0.0		sheng.zheng		初版
	 *
	 */
	public static String makeFirstUpper(String sInput) {
		String sRet = "";
		if (sInput.isEmpty()) {
			return sRet;
		}
		sRet = sInput.substring(0, 1).toUpperCase() + sInput.substring(1);
		return sRet;
	}
	
	/**
	 * 
	 * @methodName		: makeFirstLower
	 * @description	: 将首字母转为小写
	 * @param sInput	: 输入字符串
	 * @return			: 转换后的字符串
	 * @history		:
	 * ------------------------------------------------------------------------------
	 * date			version		modifier		remarks                   
	 * ------------------------------------------------------------------------------
	 * 2023/04/11	1.0.0		sheng.zheng		初版
	 *
	 */
	public static String makeFirstLower(String sInput) {
		String sRet = "";
		if (sInput.isEmpty()) {
			return sRet;
		}
		sRet = sInput.substring(0, 1).toLowerCase() + sInput.substring(1);
		return sRet;
	}	
	
	/**
	 * 
	 * @methodName		: getUpperCamelCase
	 * @description	: 将非字母和数字分隔的字符串转为大驼峰
	 * @param name		: 输入字符串
	 * @return		: 大驼峰
	 * @history		:
	 * ------------------------------------------------------------------------------
	 * date			version		modifier		remarks                   
	 * ------------------------------------------------------------------------------
	 * 2023/05/29	1.0.0		sheng.zheng		初版
	 *
	 */
	public static String getUpperCamelCase(String name) {
	    if(name == null || "".equals(name)){
	        return "";
	    }
	    String[] strings = name.split("[^a-zA-Z0-9]+");
	    StringBuilder sb = new StringBuilder();
	    for (int i = 0; i <strings.length; i++) {
	        sb.append(makeFirstUpper(strings[i]));
	    }
	    return sb.toString();
	} 	
    
    /**
     * 
     * @methodName		: getLongValue
     * @description	: 获取JSON数据中Long类型值
     * @param params	: Map类型
     * @param fieldName	: 字段名
     * @return			: Long类型值
     * @history		:
     * ------------------------------------------------------------------------------
     * date			version		modifier		remarks                   
     * ------------------------------------------------------------------------------
     * 2021/01/01	1.0.0		sheng.zheng		初版
     *
     */
    public static Long getLongValue(Map<String,Object> params,String fieldName) {
		Object objId = params.get(fieldName);
		if (objId == null) {
			return 0L;
		}
		Long longId = 0L;
		if (objId instanceof Integer) {
			Integer iId = (Integer)objId;
			longId = iId.longValue();
		}else {
			longId = (Long)objId;
		}	
		return longId;
	}  
    
    /**
     * 
     * @methodName		: calcIOU
     * @description	: 计算两个矩形的IOU值（交集面积/并集面积）
     * @param r1x1		: 矩形1的左上x轴坐标值
     * @param r1y1		: 矩形1的左上y轴坐标值
     * @param r1x2		: 矩形1的右下x轴坐标值
     * @param r1y2		: 矩形1的右下y轴坐标值
     * @param r2x1		: 矩形2的左上x轴坐标值
     * @param r2y1		: 矩形2的左上y轴坐标值
     * @param r2x2		: 矩形2的右下x轴坐标值
     * @param r2y2		: 矩形2的右下y轴坐标值
     * @return			: IOU值
     * @history		:
     * ------------------------------------------------------------------------------
     * date			version		modifier		remarks                   
     * ------------------------------------------------------------------------------
     * 2021/01/01	1.0.0		sheng.zheng		初版
     *
     */
    public static double calcIOU(int r1x1,int r1y1,int r1x2,int r1y2,
    		int r2x1,int r2y1,int r2x2,int r2y2) {
    	double retRet = 0;

    	// 先计算交集矩形
    	// 无交集情况
    	// x-轴无交集：矩形2在矩形1右边或左边
    	if (r2x1 >= r1x2 || r2x2 <= r1x1) {
    		return retRet;
    	}
    	// y-轴无交集：矩形2在矩形1上边或下边
    	if (r2y1 >= r1y2 || r2y2 <= r1y1) {
    		return retRet;
    	}
    	// 交集矩形
    	int r3x1 = 0;
    	int r3y1 = 0;
    	int r3x2 = 0;
    	int r3y2 = 0;
    	int r3Square = 0;
    	
    	r3x1 = Math.max(r1x1, r2x1);
    	r3y1 = Math.max(r1y1, r2y1);
    	r3x2 = Math.min(r1x2, r2x2);
    	r3y2 = Math.min(r1y2, r2y2);
    	if (r3x2 > r3x1 && r3y2 > r3y1) {
    		r3Square = calcSquare(r3x1,r3y1,r3x2,r3y2);
    	}else {
    		return retRet;
    	}
    	
    	// 计算两个矩形面积
    	int r1Square = calcSquare(r1x1,r1y1,r1x2,r1y2);
    	int r2Square = calcSquare(r2x1,r2y1,r2x2,r2y2);
    	// 并集面积
    	int unionSquare = r1Square + r2Square - r3Square;
    	
    	// IOU
    	retRet = r3Square * 1.0 / unionSquare;
    	return retRet;
    }
    
    /**
     * 
     * @methodName		: calcSquare
     * @description	: 计算面积
     * @param topleftx	: 矩形的左上x轴坐标值
     * @param toplefty	: 矩形的左上y轴坐标值
     * @param bottomrightx	: 矩形的右下x轴坐标值
     * @param bottomrighty	: 矩形的右下y轴坐标值
     * @return			: 矩形面积
     * @history		:
     * ------------------------------------------------------------------------------
     * date			version		modifier		remarks                   
     * ------------------------------------------------------------------------------
     * 2021/01/01	1.0.0		sheng.zheng		初版
     *
     */
    private static int calcSquare(int topleftx,int toplefty,int bottomrightx,int bottomrighty) {
    	int retValue = 0;
    	int width = bottomrightx - topleftx; 
    	int height = bottomrighty - toplefty;
    	retValue = width * height;
    	return retValue;
    }
    

	
	/**
	 * 
	 * @methodName		: getMethodByName
	 * @description	: 根据方法名称获取方法对象
	 * @param object	: 方法所在的类对象
	 * @param methodName: 方法名
	 * @return			: Method类型对象
	 * @history		:
	 * ------------------------------------------------------------------------------
	 * date			version		modifier		remarks                   
	 * ------------------------------------------------------------------------------
	 * 2021/01/01	1.0.0		sheng.zheng		初版
	 *
	 */
	public static Method getMethodByName(Object object,String methodName) {
		Class<?> class1 = object.getClass();
		Method retItem = null;
		Method[] methods = class1.getMethods();
		for (int i = 0; i < methods.length; i++) {
			Method item = methods[i];
			// System.out.println(item.getName());
			if (item.getName().equals(methodName)) {
				retItem = item;
				break;
			}
		}
		return retItem;
	}	
	
	/**
	 * 
	 * @methodName		: removeKeys
	 * @description	: 根据指定key数组，移除字典对应key的项
	 * @param params	: Map<String,Object>类型的字典
	 * @param keys		: 需要移除的key数组
	 * @history		:
	 * ------------------------------------------------------------------------------
	 * date			version		modifier		remarks                   
	 * ------------------------------------------------------------------------------
	 * 2021/01/01	1.0.0		sheng.zheng		初版
	 *
	 */
	public static void removeKeys(Map<String,Object> params,String[] keys) {
		for (int i = 0; i < keys.length; i++) {
			String key = keys[i];
			if (params.containsKey(key)) {
				params.remove(key);
			}
		}
	}
	
	/**
	 * 
	 * @methodName		: addKeys
	 * @description	: 添加key-value字条到字典中
	 * @param toMap		: 被添加的字典
	 * @param srcMap	: 源字典
	 * @param keys		: 需要添加的key数组
	 * @history		:
	 * ------------------------------------------------------------------------------
	 * date			version		modifier		remarks                   
	 * ------------------------------------------------------------------------------
	 * 2024/01/15	1.0.0		sheng.zheng		初版
	 *
	 */
	public static void addKeys(Map<String,Object> toMap,Map<String,Object> srcMap,
			String[] keys) {
		for (int i = 0; i < keys.length; i++) {
			String key = keys[i];
			if (srcMap.containsKey(key)) {
				toMap.put(key,srcMap.get(key));
			}
		}		
	}
	
	/**
	 * 
	 * @methodName		: getKeyCount
	 * @description	: 获取字典中包含指定key数组元素的个数
	 * @param params	: 参数字典
	 * @param keys		: key数组
	 * @return			: 个数
	 * @history		:
	 * ------------------------------------------------------------------------------
	 * date			version		modifier		remarks                   
	 * ------------------------------------------------------------------------------
	 * 2024/01/20	1.0.0		sheng.zheng		初版
	 *
	 */
	public static int getKeyCount(Map<String,Object> params,String[] keys) {
		int count = 0;
		for(String key : keys) {
			if (params.containsKey(key)) {
				count++;
			}
		}
		return count;
	}
	
	/**
	 * 
	 * @methodName		: getColIdxMap
	 * @description	: 获取下标的映射字典,key为大数组的下标，value为小数组的下标
	 * @param fields	: 大数组
	 * @param subFields	: 小数组
	 * @return			: 下标的映射字典
	 * @history		:
	 * ------------------------------------------------------------------------------
	 * date			version		modifier		remarks                   
	 * ------------------------------------------------------------------------------
	 * 2024/01/23	1.0.0		sheng.zheng		初版
	 *
	 */
	public static Map<Integer,Integer> getColIdxMap(String[] fields,String[] subFields){
		Map<Integer,Integer> retMap = new HashMap<Integer,Integer>();
		for(int i = 0; i < subFields.length; i++) {
			String subFieldName = subFields[i];
			for(int j = 0; j < fields.length; j++) {
				if (fields[j].equals(subFieldName)) {
					Integer idx = Integer.valueOf(j);
					retMap.put(idx, Integer.valueOf(i));
					break;
				}
			}
		}
		return retMap;
	}
	
	/**
	 * 
	 * @methodName		: checkKeyFields
	 * @description	: 检查关键字段是否缺失
	 * @param params	: 输入参数
	 * @param fieldNames: 关键字段名
	 * @history		:
	 * ------------------------------------------------------------------------------
	 * date			version		modifier		remarks                   
	 * ------------------------------------------------------------------------------
	 * 2021/01/01	1.0.0		sheng.zheng		初版
	 *
	 */
	public static void checkKeyFields(Map<String,Object> params,String[] fieldNames) {
		for(int i = 0; i < fieldNames.length; i++) {
			String fieldName = fieldNames[i];
			if (!params.containsKey(fieldName)) {
				String prompt = "，缺失字段：" + fieldName;
				throw new BaseException(ExceptionCodes.ARGUMENTS_ERROR.getCode(),
						ExceptionCodes.ARGUMENTS_ERROR.getMessage() + prompt);
			}
		}
	}
	
	/**
	 * 
	 * @methodName		: checkOpKeyFields
	 * @description	: 检查可选关键字段是否存在
	 * @param params	: 输入参数
	 * @param fieldNames: 关键字段名
	 * @history		:
	 * ------------------------------------------------------------------------------
	 * date			version		modifier		remarks                   
	 * ------------------------------------------------------------------------------
	 * 2021/01/01	1.0.0		sheng.zheng		初版
	 *
	 */
	public static void checkOpKeyFields(Map<String,Object> params,String[] fieldNames) {
		boolean bFound = false;
		String prompt = "，缺失可选字段：";
		for(int i = 0; i < fieldNames.length; i++) {
			String fieldName = fieldNames[i];
			if (params.containsKey(fieldName)) {
				bFound = true;
				break;
			}
			if (i != 0) {
				prompt += ",";
			}
			prompt += fieldName;			
		}
		if (!bFound) {
			throw new BaseException(ExceptionCodes.ARGUMENTS_ERROR,prompt);			
		}
	}	
	
	/**
	 * 
	 * @methodName		: getMapItem
	 * @description	: 如果key不存在，创建子项并加入容器字典中；最后获取对应子项
	 * @param container	: 容器字典
	 * @param key		: 容器字典的项的key
	 * @return			: 子项
	 * @history		:
	 * ------------------------------------------------------------------------------
	 * date			version		modifier		remarks                   
	 * ------------------------------------------------------------------------------
	 * 2021/01/01	1.0.0		sheng.zheng		初版
	 *
	 */
	public static Map<String,Object> getMapItem(Map<String,Map<String,Object>> container,
			String key){
		Map<String,Object> subItemMap = null;
		if (container.containsKey(key)) {
			// 如果key已存在
			subItemMap = container.get(key);
		}else {
			// 如果为新的key
			// 创建子项，并加入容器字典中
			subItemMap = new HashMap<String,Object>();
			container.put(key, subItemMap);
		}
		
		return subItemMap;
	}	
}
